home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / TEMP / GNU / flex / Multiplebu < prev    next >
Text File  |  1995-06-28  |  6KB  |  195 lines

  1. Multiple buffers
  2. Previous: <Start conditions=>Startcondi> * Next: <End-of-file rules=>Endoffiler> * Up: <Top=>!Root>
  3.  
  4. #Wrap on
  5. {fH3}Multiple input buffers{f}
  6.  
  7. Some scanners (such as those which support "include"
  8. files) require reading from several input streams.  As
  9. {fCode}flex{f} scanners do a large amount of buffering, one cannot
  10. control where the next input will be read from by simply
  11. writing a {fCode}YY\_INPUT{f} which is sensitive to the scanning
  12. context.  {fCode}YY\_INPUT{f} is only called when the scanner reaches
  13. the end of its buffer, which may be a long time after
  14. scanning a statement such as an "include" which requires
  15. switching the input source.
  16.  
  17. To negotiate these sorts of problems, {fCode}flex{f} provides a
  18. mechanism for creating and switching between multiple
  19. input buffers.  An input buffer is created by using:
  20.  
  21. #Wrap off
  22. #fCode
  23. YY\_BUFFER\_STATE yy\_create\_buffer( FILE \*file, int size )
  24. #f
  25. #Wrap on
  26.  
  27. which takes a {fCode}FILE{f} pointer and a size and creates a buffer
  28. associated with the given file and large enough to hold
  29. {fStrong}size{f} characters (when in doubt, use {fCode}YY\_BUF\_SIZE{f} for the
  30. size).  It returns a {fCode}YY\_BUFFER\_STATE{f} handle, which may
  31. then be passed to other routines (see below).  The
  32. {fCode}YY\_BUFFER\_STATE{f} type is a pointer to an opaque {fCode}struct{f}
  33. {fCode}yy\_buffer\_state{f} structure, so you may safely initialize
  34. YY\_BUFFER\_STATE variables to {fEmphasis}((YY\_BUFFER\_STATE) 0){f} if you
  35. wish, and also refer to the opaque structure in order to
  36. correctly declare input buffers in source files other than
  37. that of your scanner.  Note that the {fCode}FILE{f} pointer in the
  38. call to {fCode}yy\_create\_buffer{f} is only used as the value of {fCode}yyin{f}
  39. seen by {fCode}YY\_INPUT{f}; if you redefine {fCode}YY\_INPUT{f} so it no longer
  40. uses {fCode}yyin{f}, then you can safely pass a nil {fCode}FILE{f} pointer to
  41. {fCode}yy\_create\_buffer{f}.  You select a particular buffer to scan
  42. from using:
  43.  
  44. #Wrap off
  45. #fCode
  46. void yy\_switch\_to\_buffer( YY\_BUFFER\_STATE new\_buffer )
  47. #f
  48. #Wrap on
  49.  
  50. switches the scanner's input buffer so subsequent tokens
  51. will come from {fStrong}new\_buffer{f}.  Note that
  52. {fEmphasis}yy\_switch\_to\_buffer(){f} may be used by {fEmphasis}yywrap(){f} to set
  53. things up for continued scanning, instead of opening a new
  54. file and pointing {fCode}yyin{f} at it.  Note also that switching
  55. input sources via either {fEmphasis}yy\_switch\_to\_buffer(){f} or {fEmphasis}yywrap(){f}
  56. does {fEmphasis}not{f} change the start condition.
  57.  
  58. #Wrap off
  59. #fCode
  60. void yy\_delete\_buffer( YY\_BUFFER\_STATE buffer )
  61. #f
  62. #Wrap on
  63.  
  64. is used to reclaim the storage associated with a buffer.
  65. You can also clear the current contents of a buffer using:
  66.  
  67. #Wrap off
  68. #fCode
  69. void yy\_flush\_buffer( YY\_BUFFER\_STATE buffer )
  70. #f
  71. #Wrap on
  72.  
  73. This function discards the buffer's contents, so the next time the
  74. scanner attempts to match a token from the buffer, it will first fill
  75. the buffer anew using {fCode}YY\_INPUT{f}.
  76.  
  77. {fEmphasis}yy\_new\_buffer(){f} is an alias for {fEmphasis}yy\_create\_buffer(){f},
  78. provided for compatibility with the C++ use of {fCode}new{f} and {fCode}delete{f}
  79. for creating and destroying dynamic objects.
  80.  
  81. Finally, the {fCode}YY\_CURRENT\_BUFFER{f} macro returns a
  82. {fCode}YY\_BUFFER\_STATE{f} handle to the current buffer.
  83.  
  84. Here is an example of using these features for writing a
  85. scanner which expands include files (the {fEmphasis}<<EOF>>{f} feature
  86. is discussed below):
  87.  
  88. #Wrap off
  89. #fCode
  90. \/\* the "incl" state is used for picking up the name
  91.  \* of an include file
  92.  \*\/
  93. %x incl
  94.  
  95. %\{
  96. \#define MAX\_INCLUDE\_DEPTH 10
  97. YY\_BUFFER\_STATE include\_stack[MAX\_INCLUDE\_DEPTH];
  98. int include\_stack\_ptr = 0;
  99. %\}
  100.  
  101. %%
  102. include             BEGIN(incl);
  103.  
  104. [a-z]+              ECHO;
  105. [^a-z\\n]\*\\n?        ECHO;
  106.  
  107. <incl>[ \\t]\*      \/\* eat the whitespace \*\/
  108. <incl>[^ \\t\\n]+   \{ \/\* got the include file name \*\/
  109.         if ( include\_stack\_ptr >= MAX\_INCLUDE\_DEPTH )
  110.             \{
  111.             fprintf( stderr, "Includes nested too deeply" );
  112.             exit( 1 );
  113.             \}
  114.  
  115.         include\_stack[include\_stack\_ptr++] =
  116.             YY\_CURRENT\_BUFFER;
  117.  
  118.         yyin = fopen( yytext, "r" );
  119.  
  120.         if ( ! yyin )
  121.             error( … );
  122.  
  123.         yy\_switch\_to\_buffer(
  124.             yy\_create\_buffer( yyin, YY\_BUF\_SIZE ) );
  125.  
  126.         BEGIN(INITIAL);
  127.         \}
  128.  
  129. <<EOF>> \{
  130.         if ( --include\_stack\_ptr < 0 )
  131.             \{
  132.             yyterminate();
  133.             \}
  134.  
  135.         else
  136.             \{
  137.             yy\_delete\_buffer( YY\_CURRENT\_BUFFER );
  138.             yy\_switch\_to\_buffer(
  139.                  include\_stack[include\_stack\_ptr] );
  140.             \}
  141.         \}
  142. #f
  143. #Wrap on
  144.  
  145. Three routines are available for setting up input buffers
  146. for scanning in-memory strings instead of files.  All of
  147. them create a new input buffer for scanning the string,
  148. and return a corresponding {fCode}YY\_BUFFER\_STATE{f} handle (which
  149. you should delete with {fEmphasis}yy\_delete\_buffer(){f} when done with
  150. it).  They also switch to the new buffer using
  151. {fEmphasis}yy\_switch\_to\_buffer(){f}, so the next call to {fEmphasis}yylex(){f} will
  152. start scanning the string.
  153.  
  154. #Indent +4
  155. #Indent
  156. {fEmphasis}yy\_scan\_string(const char \*str){f}
  157. #Indent +4
  158. scans a NUL-terminated string.
  159.  
  160. #Indent
  161. {fEmphasis}yy\_scan\_bytes(const char \*bytes, int len){f}
  162. #Indent +4
  163. scans {fCode}len{f} bytes (including possibly NUL's) starting
  164. at location {fStrong}bytes{f}.
  165.  
  166. #Indent
  167.  
  168. Note that both of these functions create and scan a {fEmphasis}copy{f}
  169. of the string or bytes.  (This may be desirable, since
  170. {fEmphasis}yylex(){f} modifies the contents of the buffer it is
  171. scanning.) You can avoid the copy by using:
  172.  
  173. #Indent +4
  174. #Indent
  175. {fEmphasis}yy\_scan\_buffer(char \*base, yy\_size\_t size){f}
  176. #Indent +4
  177. which scans in place the buffer starting at {fStrong}base{f},
  178. consisting of {fStrong}size{f} bytes, the last two bytes of
  179. which {fEmphasis}must{f} be {fCode}YY\_END\_OF\_BUFFER\_CHAR{f} (ASCII NUL).
  180. These last two bytes are not scanned; thus,
  181. scanning consists of {fEmphasis}base[0]{f} through {fEmphasis}base[size-2]{f},
  182. inclusive.
  183.  
  184. If you fail to set up {fStrong}base{f} in this manner (i.e.,
  185. forget the final two {fCode}YY\_END\_OF\_BUFFER\_CHAR{f} bytes),
  186. then {fEmphasis}yy\_scan\_buffer(){f} returns a nil pointer instead
  187. of creating a new input buffer.
  188.  
  189. The type {fCode}yy\_size\_t{f} is an integral type to which you
  190. can cast an integer expression reflecting the size
  191. of the buffer.
  192.  
  193. #Indent
  194.  
  195.